Workshop 2 - Core Python Concepts

There is a sign-in sheet, sign in or you wont get credit for attendance today!

  • Today:
    Today we will take our first steps in programming in python. We will only be using 'core' python functions. Todays workshop is focused on the fundamentals of programming.
    The next several fridays will be more like Labs, to get credit for the day you have to show that you have done all of the problems in todays workshop notebook. I will briefly go over the pieces of this workshop at the beginning of class. Working together is encouraged, and don't be afraid to ask me questions.


Goals for Today:

You can download todays notebook from   github.com/dahlend/Physics77Fall17
0) Variables
1) What is a function
2) Take input from a command line
3) Conditional Statements
4) Loops
5) Combining loops and conditional statements
5) Create your own function
6) Practice Problems

Running Python in Jupyter:

You can run a 'block' of code with 'shift + enter' or 'ctrl + enter' or pressing the 'play' button at the top of the screen.

Code Comments

Comments in code exist to explain now the code works to others (or more commonly to yourself).

A comment is ignored by python, it just Skips everything inside the comment.

Comments are done with the # symbol. Everything on the line AFTER the # is just ignored.

Add comments often! It's easy to skip this, but it's super important. Comments in your code also show that you understand what you are doing, adding comments to code you submit for homework in this class can be the difference between a A and a B on an assignment.

0) Variables


In [ ]:
# in python (and almost every other programming language)
# the = sign is a definition

# For example, I can define a value 'x' to be 5:
x = 5

# or 'y' to be 'cat'
y = 'cat'


# lets look at our variables:
x, y

In [ ]:
# These definitions always happen in this order
# variable being set = value i'm setting it to

# I can then do stuff with variables:
a = 3
b = 17

c = a + b

c

1) Functions


In [ ]:
# A lot of programming is based on the concept of a function
# a function in math is written like:

# y = f(x)

# where if I pass a value x to f, f(x) returns the value y
# Similarly in python this is true:

# I'll define an x in this case to be a list of numbers
x = [1, 2, 3, 4]

# now I can sum them, where sum(x) is a function which accepts x as an input
sum(x) # 1 + 2 + 3 + 4 = 10

In [ ]:
# Note that print is a function!

print("Hi, I'm a function")

In [ ]:
# What if I don't know what a function does?
# There's a function for that!

help(sum)

2) Input from command line


In [ ]:
# There are several ways to bring data into python, today we will use 'input'

# This line of code takes input from the user, and sets a variable 
# to be the value which was entered.
# In this case we enter a number and the variable "num_from_input" will be that value

num_from_input = input("Heres an example of input, enter a number: ")

# We can print that value back out to the user to show that it saved:
print("You Entered: ", num_from_input)

# Try it out, importantly try entering something which is NOT a number

What Happened?

After entering something which is not a number, what happened?

But the input line said to enter a number, and it didn't say an error when you ran it.
In general you can't trust people to put in the correct thing, so you need to Check it!

The technical name for this is input "sanitization", but really it comes down to checking if the input is what you expect.

An simple way around this is to ENFORCE the type you expect.

In this case we want an integer.


In [ ]:
# This line is the same as above, but I included int(), int is a function that makes
# whatever is passed to it into an Integer, and if it can't do it, it raises an error
num_from_input = int(input("Heres an example of input, enter a number: "))

print("You Entered: ", num_from_input)
print("5 + (Your Number) = ", 5 + num_from_input)

Types of variables

Python allows for many types of variables, above we demonstrated integers (ints), Here is a partial list of allowed values:

Type Name Example
int() Integer 1337
float() decimal number -2345.12
complex() complex number 7-1j
string() text "Hello World"
list() list of things ['c', 1, 3, 1j]
bool() boolean (True or False) True

3) Conditional Statements

A conditional statement is often called an if statement.

It looks something like this:

if (some condition):  
    if the condition is true, run code which is indented here
else:  
    run this code if the condition is not met

In [ ]:
# Set some variables
a = float(input("Enter a number, a="))
b = 4.0
print("a =", a, "  ,b =", b)


# this line reads, if a is greater than b, print("a > b")
if a > b:
    print("a > b")
else:  # if it is NOT the above condition, do this
    print("a <= b")

You can compare with the following operators:

Operator Name
> greater than
< less than
== equal
>= greater than or equal
<= less than or equal
!= not equal

Since = is use to define variables, we cant use it to compare two values, which is why there is ==

4) Loops

Lets say I want to print out all the numbers from 1 through 10, and 2x their value


In [ ]:
# we can use a python function, range() to make a range of numbers

# This makes a list of numbers from 1 to 10
list_of_nums = range(1, 11)

# range() doesn't include the last element, so no 11 in this case

list(list_of_nums)  # We see we a have a list of numbers from 1 to 10

In [ ]:
# I want 2 * list_of_nums

2 * list_of_nums

Great! Now we have a list of 1 to 10, but I need to multiply everything by 2.

Unfortunately I can't just print 2*list_of_nums, but I CAN go through the list and
print 2*i for each number in the list


In [ ]:
# So lets 'iterate' through the list

# This is done with a 'for' loop
# as in "For each number i in the list of numbers [1, 2, ..., 10]: run this code"
for i in list_of_nums:
    print("i = ", i)
    print("2*i = ", 2 * i)
    
# Code indented in the for loop repeats itself until it goes through all the numbers in the list

5) Combining Concepts!

Lets go through the numbers 1 through 10, and identify when we have found the number 6.

This can be done by combining the two things above.


In [ ]:
for i in list_of_nums:
    if i == 6:
        print("i is 6!!! Woo!")
    else:
        print("i = ", i, ",  booo not 6 :(")

In [ ]:
# What about listing all the numbers which are even from 1 to 10?
for i in list_of_nums:
    if i % 2 == 0:
        print("I is even, i =", i)

Digression

What is this % thing? It's called Modulo, if you haven't seen it before:

The modulo is the remainder after a division, equivalently there is another operator //
which returns the divisible portion of the numerator. Examples might be more instructive:


In [ ]:
# 12 / 5 = 2 remainder 2
print("12 / 5 =", 12 // 5, 'remainder', 12 % 5)

# 15 / 4 = 3 remainder 3
print("15 / 4 =", 15 // 4, 'remainder', 15 % 4)

# 6 / 2 = 3 remainder 0
# NOTE: when the remainder is 0 then 6 is divisible by 2

# This is what is used above to decide when numbers are even.
print("6 / 2 =", 6 // 2, 'remainder', 6 % 2, "  ,6 is divisible by 2. remainder = 0")

Let's say I want to count how many numbers there are which are divisible by 7 below 100?


In [ ]:
# First lets make a variable which keeps track of the number
# of numbers which are divisible by 7, at first we haven't
# found any yet, so it is 0.
n_div_7 = 0

for i in range(1, 100):
    # For each number from 1 to 100 we check
    # to see if it is divisible by 7, if it is, we add 1 to our counter
    
    # is i divisble by 7?
    if i % 7 == 0:
        # above we saw that if i % 7 == 0, you know that i is divisible by 7
        print(i, "is divisible by 7")
        
        # so here the counter is set to the counter + 1
        n_div_7 = n_div_7 + 1
        
print("There are", n_div_7, "numbers below 100 which are divisible by 7.")

6) Defining your own function


In [ ]:
# Below is a function definition in python, this allows you to define your own functions.
# This function accepts these variables:
#     Accepts:
#         x - must be a number
#         y - must also be a number
#     Returns:
#         x + y


# def - short for defintion
def my_sum(x, y):
    return x + y

my_sum(3, 5)

In [ ]:
def my_func(x, y):
    print("Lets look at math operators in python:")
    print("X =", x, ", Y =", y)
    print("X * Y = ", x * y)
    print("X / Y = ", x / y)
    print("X + Y = ", x + y)
    print("X - Y = ", x - y)
    print("X // Y = ", x // y)  # floor division
    print("X % Y = ", x % y)  # Modulo
    print("X to the power of Y you will have to look up!")
    
    print("This function is going to return x+y")    
    return x + y


# Now lets use the function we defined!
my_func(x=6, y=7)

Problems:

Problem 0 - Using tools from sections (0, 1, 2) above:

Write some code which takes 2 inputs from the user, puts the data into 2 variables, a, b, and multiplies the variables together.

Make sure that if a user enters something which is NOT an integer it errors immediately!


In [ ]:
# Your code goes here!

print("a * b = ", )

Problem 1 - sections (0, 1, 2):

Same as above, but take 2 inputs, a, and b, and return a^b.

I haven't told you how to do powers in python! Google!

Google suggestion:
"python exponent"


In [ ]:
# Your code goes here!

print("a^b = ", )

Problem 2 - sections (0, 1, 2, 4):

What does this equal:
$$-4 + 4\cdot \sum_{k=1}^{10^6} \frac{(-1)^{k+1}}{2k-1}$$

Hint:

You can use a for loop like this:


In [ ]:
val = 0

for k in range(1000):
    # each k is added to the previous val and val is updated to that
    val = val + k

val

In [ ]:
# Your Code goes here

Problem 3 - sections (0, 1, 2, 3, 4 ,5):

How many numbers from 1 to 2000 are divisible by both 3, and 7?

(Use the Modulo operator % - see above)

Helpful Hint:

You can combine conditional statements like so:


In [ ]:
a = 2
b = 6.

if a == 2 and b < 7.14:
    print("a == 2 AND b < 7.14")
else:
    print("Either a != 2 or b > 7.14, I can't tell the difference")

In [ ]:
# Your code goes here!

Problem 4 - sections (0, 1, 2, 3, 4 ,5):

For each number i, from 1 to 10000, tell me how many meet this condition:

10000 < i^3. - 0.5*i^2.9999 - 0.5*i^3.0001 + 50*i < 14125


In [ ]:
# Your code here!

Problem 5 - All Sections!

This problem is different then the last, I'm providing you with ~80 lines of code which I have already written.

You have to make the correct changes to ~2 of the lines.

When this is done it will be a not-quite perfect simulation of ball falling in gravity.

Here is an outline of how this works:

There are two functions here, one of which is the simulation, which you shouldn't edit.
The other function is "update_motion", inside this function there are currently the statements:

v_final = v
y_final = y

You need to update these lines to correctly calculate the position/velocity of a ball as it falls.

No calculus is required, if the ball is falling at velocity v, is at position y, where will it be at some small time later dt, and how fast will it be going.

If you update those lines correctly, when you run this code you will see a simple simulation of a ball bouncing.


In [ ]:
y_init = 10  # meters, initial position of the ball
v_init = 0.0  # m/s, initial velocity of the ball
gravity = -9.81  # m/s^2

dt = 0.01  # seconds, how much time between timesteps
n_timesteps = 1000  # how many steps of time 


def update_motion(y, v, dt):
    """This function takes the y-position of a ball, the velocity in the y direction,
    and how much time has passed, and returns where the ball will be at the next point in time.
     y - Current position in meters
     v - current velocity in meters/second
     dt - how much time is passing
    """
    
    #  The ball is currently at velocity v, and is at position x
    #  where will it be some time dt later?
    y_final = y      # Put the correct equations of motion here!
    
    # Similarly, how will it's velocity change due to gravity?
    v_final = v      # Put the correct equations of motion here!
    
    return y_final, v_final


def run_simulation(y_0, v_0, dt, n_steps):
    """Runs a simulation of a ball, the update of position and velocity,
    is done by evaluating the function update_motion with the current
    position, velocity and how much time has elapsed between timesteps.
    At the end of the simulation it plots the results."""
    
    # We need to keep track of all of the positions and velocities
    # that we calculate so that we can plot the results of our
    # simulation.
    
    # To do this we make a list, which is empty, then add
    # our calculated values to the list. We will return the
    # values and plot them afterward.
    y_history = []
    v_history = []
    time_history = []

    print("Simulating {} seconds of time in {} steps.".format(n_timesteps * dt, n_timesteps))

    y_current = y_0
    v_current = v_0
    for step_i in range(0, n_timesteps):
        y_history.append(y_current)
        v_history.append(v_current)
        time_history.append(step_i*dt)
        
        y_current, v_current = update_motion(y_current, v_current, dt)
        
        # If the ball is below 0, it should bounce,
        # This means its velocity will change sign
        if y_current <= 0:
            v_current = -v_current
        
        
    # The rest of the code is for plotting only!
    # all the numerical simulation happened the the lines above
    import matplotlib.pyplot as plt
    get_ipython().magic(u'matplotlib inline')

    plt.figure(figsize=(8,6))
    plt.subplot(2,1,1)
    plt.plot(time_history, y_history, label='Ball Position')
    plt.axhline(0, color='black', label='Ground')
    plt.legend()
    plt.ylabel("Height (m)")
    plt.title("Height of the ball");

    plt.subplot(2,1,2)
    plt.plot(time_history, v_history, color='green')
    plt.xlabel("Time (s)")
    plt.ylabel("Velocity (m/s)")
    plt.title("Velocity of the ball");
    plt.tight_layout()

run_simulation(y_init, v_init, dt, n_timesteps)